package com.justgame.project.cloud.common.util;


import com.justgame.project.cloud.common.constant.Const;
import com.justgame.project.cloud.common.enums.TimeEnum;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;

/**
 * 验证码生成器
 */
@Slf4j
public class AuthCodeUtils {
    private final int widthPX = 100;  //设置图片宽度
    private final int heightPX = 40;  //设置图片高度
    private final Color bgColor = new Color(255, 255, 255); //设置图片背景
    private final Random random = new Random();
    /**
     * 设置 字体、字号、样式
     *
     * @return
     */
    private final String[] fontName = {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑"};
    private final int[] fontSize = {28, 32, 35};

    private final String codes = "abcdefghijklmnopqrstuvwxyz0123456789";
    StringBuilder sb = new StringBuilder();

    public static void saveImage(BufferedImage img, OutputStream out) throws Exception {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(img, "png", os);
        InputStream in = new ByteArrayInputStream(os.toByteArray());
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = in.read(buff, 0, 100)) > 0) {
            out.write(buff, 0, rc);
        }
    }

    //默认条件下生成验证码
    public static void defaultBuild() {
        AuthCodeUtils util = new AuthCodeUtils();
        OutputStream out = null;
        HttpServletResponse response = HttpContextUtil.getHttpResponse();
        try {
            out = response.getOutputStream();
            AuthCodeUtils.saveImage(util.getImage(), out);
            String code = util.getText().toLowerCase();
            StringBuffer sb = Encryption.PasswordMD5(code, Const.DEFAULT_SALT_VERIFICATION);
            String md5VCode = String.valueOf(sb);
            ShiroUtils.setSessionAttribute(Const.KEY_VERIFICATION_CODE_2WEB, md5VCode);
            AppContextUtils.getBean(RedisUtil.class).set(String.valueOf(ShiroUtils.getSession().getId()), md5VCode, TimeEnum.MINUTE.getTime(15) / 1000);
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException ioe) {
                log.error(ioe.getMessage());
            }
        }
    }

    private BufferedImage createImage() {
        /*
         * 1.创建图片
         * 2.设置背景色
         */
        BufferedImage img = new BufferedImage(widthPX, heightPX, BufferedImage.TYPE_INT_RGB);
        //设置画笔颜色
        Graphics2D graphics2d = (Graphics2D) img.getGraphics();
        graphics2d.setColor(this.bgColor);
        graphics2d.fillRect(0, 0, widthPX, heightPX);
        //填充图片大小的矩形（设置背景色）
        return img;
    }

    private Color randomColor() {
        /* 70-170（深色） */
        int r = random.nextInt(100) + 70;
        int g = random.nextInt(100) + 70;
        int b = random.nextInt(100) + 70;
        return new Color(r, g, b);
    }

    private Font randomFont() {
        int index = random.nextInt(fontName.length);
        //根据随机索引获取字体名
        String name = fontName[index];
        //设置字体样式
        int style = random.nextInt(4);
        index = random.nextInt(fontSize.length);
        //根据索引获取字体大小
        int size = fontSize[index];
        return new Font(name, style, size);
    }

    private String randomChar() {
        int index = random.nextInt(codes.length());
        //返回随机字符
        return codes.charAt(index) + "";
    }

    private void drawLine(BufferedImage image) {
        int num = 3;
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        for (int i = 0; i < num; i++) {
            int x1 = random.nextInt(widthPX);
            int y1 = random.nextInt(heightPX);
            int x2 = random.nextInt(widthPX);
            int y2 = random.nextInt(heightPX);
            g2.setStroke(new BasicStroke(1.5F));
            g2.setColor(Color.BLUE);
            g2.drawLine(x1, y1, x2, y2);
        }
    }

    public BufferedImage getImage() {
        /**
         * 写入字符（包括字符字体、颜色、字符种类）
         */
        BufferedImage img = this.createImage();
        Graphics g = img.getGraphics();
        for (int i = 0; i < 4; i++) {
            //设置字符
            String ch = this.randomChar();
            sb.append(ch);
            //设置画笔颜色
            g.setColor(this.randomColor());
            //设置画笔字体
            g.setFont(this.randomFont());
            //画出字符
            g.drawString(ch, widthPX / 4 * i, heightPX - 5);
        }
        drawLine(img);
        return img;
    }

    //获取验证码的字符
    public String getText() {
        return sb.toString();
    }

}
